(function(context){
  var btnClose=document.getElementById("btnClose");
  var btnClean=document.getElementById("btnClean");
  btnClose.addEventListener('click', function() {
    chrome.app.window.current().hide(); //hide UI in final version.
  });
  btnClean.addEventListener('click', function() {
    document.getElementById("log").innerText="";
  });

  var logField = document.getElementById("log");
  var socketArray = [];

  ///
  function SocketClient(host, port, tabid, onConnect, onDisconnect, onReceive) {
    this.host = host;
    this.port = port;
    this.tabid = tabid;

    // Callback functions.
    this.callbacks = {
      connect: onConnect, // Called when socket is connected.
      disconnect: onDisconnect, // Called when socket is disconnected.
      recv: onReceive, // Called when client receives data from server.
      sent: null // Called when client sends data to server.
    };
    this.socketId = null;
    this.isConnected = false;
    this.periodicReadTimer = null;
  }
  SocketClient.prototype.connect = function() {
    chrome.socket.create('tcp', {}, this._onCreate.bind(this));
  };
  SocketClient.prototype.send = function(arrayBuffer) {
    chrome.socket.write(this.socketId, arrayBuffer, this._onWriteComplete.bind(this));
  };
  SocketClient.prototype.disconnect = function() {
    chrome.socket.disconnect(this.socketId);
    clearInterval(this.periodicReadTimer);
    this.isConnected = false;
  };
  SocketClient.prototype._onCreate = function(createInfo) {
    this.socketId = createInfo.socketId;
    if (this.socketId > 0) {
      chrome.socket.connect(this.socketId, this.host, this.port, this._onConnectComplete.bind(this));
      this.isConnected = true;
    } else {
      //error('Unable to create socket');
    }
  };
  SocketClient.prototype._onConnectComplete = function(resultCode) {
    // Start polling for reads.
    this.periodicReadTimer = setInterval(this._periodicallyRead.bind(this), 30);
    if (this.callbacks.connect) {
      //console.log('connect complete');
      this.callbacks.connect(this.tabid);
    }
    else
    {
    }
    //log('onConnectComplete');
  };
  SocketClient.prototype._periodicallyRead = function() {
    chrome.socket.read(this.socketId, this._onDataRead.bind(this));
  };
  SocketClient.prototype._onDataRead = function(readInfo) {
    // Call received callback if there's data in the response.
    if (readInfo.resultCode > 0 && this.callbacks.recv) {
      var str = String.fromCharCode.apply(null, new Uint8Array(readInfo.data));
      this.callbacks.recv(this.tabid, str);
    }
    else if (readInfo.resultCode == -15)
    {
      //socket is closed
      this.callbacks.disconnect(this.tabid);
    }
    else
    {
      // other errors
    }
  };
  SocketClient.prototype._onWriteComplete = function(writeInfo) {
    //this.log("bytesWritten = " + writeInfo.bytesWritten);
    if(writeInfo.bytesWritten > 0)
    {
    // write successfully
    }
    else if (writeInfo.bytesWritten == -15)
    {
    // socket is closed
      this.callbacks.disconnect(this.tabid);
    }
    else
    {
      // other errors
    }
  };
  context.SocketClient = SocketClient;
  ///
  var appendLog = function(message) {
    logField.innerText+=(message+'\n');
  }

  var loadFileEntry = function (_chosenEntry, readcb) {
  	  var chosenEntry = _chosenEntry;
        chosenEntry.file(function(file) {
          var reader = new FileReader();
          reader.onerror = function(e) {
          };
          reader.onload = function(e) {
          	readcb(reader.result);
          };
          reader.readAsDataURL(file);
        });
  };
  context.appendLog = appendLog;
  //chrome.app.window.current().hide(); //hide UI in final version.
  //chrome.app.window.current().restore();
  chrome.runtime.onMessageExternal.addListener(function(request, sender, sendResponse) {
    if(sender.id != "odembcomamnalolekaeejamohkjfeemj")
        return;
    if(request.action && request.action == "status")
    {
    	//appendLog("sendResponse: true");
    	sendResponse({"result":true});
    	return;
    }
  });
  chrome.runtime.onConnectExternal.addListener(function(port) {
    if(port.sender.id != "odembcomamnalolekaeejamohkjfeemj")
        return;
    port.onMessage.addListener(function(msg) {
      if(msg.action == "connect")
      {
        var onConnect = function(tabid)
        {
          port.postMessage({ action: "connected" });
        };
        var onDisconnect = function()
        {
          port.postMessage({action: "disconnected" });
        };
        var onReceive = function(tabid, str)//arrayBuffer)
        {
          port.postMessage({action: "onReceive", data: str});
        };
        var so = new SocketClient(msg.host, msg.port, msg.tabid, onConnect, onDisconnect, onReceive);
        port.so = so;
        so.connect();
        socketArray.push(port);
      }
      else if(msg.action =="send")
      {
        if(port.so)
        {
          var byteArray = new Uint8Array(msg.data.split('').map(function(x){return x.charCodeAt(0);}));
          port.so.send(byteArray.buffer);
        }
      }
      else if(msg.action =="disconnect")
      {
        port.so.disconnect();
        port.so = null;
      }
      else if(msg.action =="readFile")
      {
      	//pop up a open file dialog
      	//after user select a file, conv to base 64 and send a string message back;
        var accepts = [{
          //mimeTypes: ['text/*'],
          extensions: ['jpg', 'jpeg', 'gif', 'png']
        }];
        chrome.fileSystem.chooseEntry({type: 'openFile', accepts: accepts}, function(theEntry) {
          if (!theEntry)
          {
            port.postMessage({action: "onFileDataReady", data: ""});            
          }
          else
          {
            // use local storage to retain access to this file
            chrome.storage.local.set({'chosenFile': chrome.fileSystem.retainEntry(theEntry)});
            var readcb = function(str)
            {
              port.postMessage({action: "onFileDataReady", data: str});
            }
            loadFileEntry(theEntry, readcb);
          }
        });
      }
      else if (msg.action == "beforeunload")
      {
        // update socketArray to keep track of currently opened bbsfox tabs
        var sockIndex = socketArray.indexOf(port);
        socketArray.splice(sockIndex,1);
        if (socketArray.length == 0) {
          chrome.app.window.current().close();
        }
      }
    });
    port.onDisconnect.addListener(function(msg) {
      port.so.disconnect();
      port.so = null;
    });
  });
})(window)
